--request.lua
-- 处理传过来的协议的调用
local filename = "tablerequest.lua"

require "skynet.manager"
require "cpcqsscenum"

local skynet = require "skynet"
local filelog = require "filelog"
local tabletool = require "tabletool"
local timetool = require "timetool"
local timer = require "timer"
local cluster = require "skynet.cluster"

local json = require "cjson"
json.encode_sparse_array(true, 1, 1)

local CMD = {}
local service = nil
local tablelogic = nil

function CMD.init(caller)
	service = caller
	tablelogic = service:get_logicbyname("tablelogic")
end

--[Comment]
-- 处理发来的request类消息
--
function CMD.request( msgname, rid, roledata, request, ...)
    --转化request协议
    local is_request = false
    if msgname == "request" then
        msgname = request.msgname or ""
        request = json.decode(request.msgbody) or { }
        is_request = true
    end

    local f = CMD[msgname]
    if f == nil then
        return {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "消息不存在！"}
    end

    local tableobj = service.table_data
    if not tableobj.is_ingame then
        tableobj.last_heart_time = timetool.get_time()
    end
    
    local responsemsg = {}

    --删除桌子中，返回错误
    if tableobj.isdeleting then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "桌子不存在！"
    else
        responsemsg = f(rid, roledata, request, ...)
    end

    --request消息转化消息格式
    if is_request then
        return { msgname = msgname .. "R", msgbody = responsemsg}
    end
    
    return responsemsg
end

-------------------------

--[Comment]
-- 创建桌子
--正常情况table不会收到该消息
-- rid  玩家id
-- roledata 玩家信息 {info,money}
--
function CMD.createtable( rid, roledata,request)
    local table_service = service.table_data.table_service
    local table_index = service.table_data.index

    --重新通知gate，玩家进桌
    local curmoney = tablelogic.get_curmoney({playerinfo = roledata.money})
    skynet.send(".router","lua","notice_gate_entertable",nil,rid,table_service,table_index,curmoney)
    return { retcode = EErrCode.ERR_HAD_IN_TABLE,retstr = "已经在桌内!"}
end

--[Comment]
-- 进桌
-- 正常由router调起,request为空
-- rid  玩家id
-- roledata 玩家信息 {info,money}
-- ret 返回table_gameinfo（牌局信息）
--
function CMD.entertable( rid, roledata,request)
	local response = {}
    local playerinfo = roledata.info or { }
    local playermoney = roledata.money or { }
	local table_data = service.table_data

    --删除桌子中，返回错误
    if table_data.isdeleting then
        response.retcode = EErrCode.ERR_INVALID_REQUEST
		response.retstr = "桌子不存在！"
		return	response
    end

  --   --检测是否已在其他桌子内
    if not roledata.is_robot and cluster.call("gatenode", ".router", "check_role_state", rid, 0) then
        response.retcode = EErrCode.ERR_HAD_IN_TABLE
		response.retstr = "已经在桌子内"
		return	response
    end

    if request and request.table_index and request.table_index ~= table_data.index then
        response.retcode = 0--EErrCode.ERR_HAD_IN_TABLE
		response.retstr = ""--"已经在桌内！"
		return	response
    end

	if table_data.sitdown_player_num >= table_data.conf.max_player_num then
		response.retcode = EErrCode.ERR_TABLE_FULL
		response.retstr = "房间人数已满！"
		return	response
	end

   --检查携带量
   local curmoney = tablelogic.get_curmoney({playerinfo = playermoney})
   if tablelogic.is_diamondtable() or tablelogic.is_cointable() then
        local min_carry = table_data.conf.min_carry_amount or 0
        local max_carry = table_data.conf.max_carry_amount or 0
        local cur_carry = curmoney
        if cur_carry < min_carry or cur_carry > max_carry then
            response.retcode = EErrCode.ERR_INVALID_PARAMS
			response.retstr = "携带量不满足入场要求！"
			return	response
        end
	end

    --获得座位
    seat = tablelogic.get_seat_by_rid(table_data, rid)
	if seat ~= nil then
		seat.playerinfo.rolename = playerinfo.rolename
		seat.playerinfo.logo = playerinfo.logo
		seat.playerinfo.sex = playerinfo.sex
        seat.playerinfo.ip_addr = roledata.ip_addr or playerinfo.ip_addr
        filelog.print("重进桌子!")
	end

    --执行进桌逻辑
    tablelogic.entertable(table_data, rid, roledata, request, seat)

    --  --自动坐下
    local result = CMD.sitdowntable(rid, roledata, {})
    if not result or result.retcode ~= nil then
        return result
    end

    --返回牌局信息
	response.table_gameinfo = tablelogic.copy_table_gameinfo(result.seat_index)
	return response
end

--[Comment]
-- 坐下
-- rid  玩家id
-- roledata 玩家信息 {info,money}
-- request 请求包
-- ret 
--
function CMD.sitdowntable(rid, roledata, request)
	local responsemsg = { }

	local table_data = service.table_data
    local playermoney = roledata.money or { }
    local playerinfo = roledata.info or { }

   --检查携带量
   local curmoney = tablelogic.get_curmoney({playerinfo = playermoney})
   if tablelogic.is_diamondtable() or tablelogic.is_cointable() then
        local min_carry = table_data.conf.min_carry_amount or 0
        local max_carry = table_data.conf.max_carry_amount or 0
        local cur_carry = curmoney
        if cur_carry < min_carry or cur_carry > max_carry then
            response.retcode = EErrCode.ERR_INVALID_PARAMS
			response.retstr = "携带量不满足入场要求！"
			return	response
        end
	end

	local seat = tablelogic.get_seat_by_rid(table_data, rid)
	if seat ~= nil then
		seat.playerinfo.rolename = playerinfo.rolename
		seat.playerinfo.logo = playerinfo.logo
		seat.playerinfo.sex = playerinfo.sex
        seat.playerinfo.ip_addr = roledata.ip_addr or playerinfo.ip_addr
        if seat.state ~= ECQSSCSeatState.SEAT_STATE_NO_PLAYER then
            responsemsg.retcode = 0--EErrCode.ERR_HAD_IN_SEAT
            responsemsg.retstr = ""--"已经在座位上!"
        end
		return responsemsg
	else
		if tablelogic.is_full(table_data) then
			responsemsg.retcode = EErrCode.ERR_TABLE_FULL
			responsemsg.retstr = "当前桌子已经满了！"
			return responsemsg
		end
		if not request.seat_index or request.seat_index == 0 then
			seat = tablelogic.get_emptyseat_by_index(table_data, nil)
		else
			seat = tablelogic.get_emptyseat_by_index(table_data, request.seat_index)
		end

		if seat == nil then
			responsemsg.retcode = EErrCode.ERR_NO_EMPTY_SEAT
			responsemsg.retstr = "当前桌子没有空座位了！"
			return responsemsg
		end
		if seat.state ~= ECQSSCSeatState.SEAT_STATE_NO_PLAYER then
			responsemsg.retcode = EErrCode.ERR_NOT_NO_PLAYER
			responsemsg.retstr = "座位不是没有玩家的状态！"
			return responsemsg
		end
		--增加桌子人数计数 
		table_data.sitdown_player_num = table_data.sitdown_player_num + 1		
	end
	tablelogic.sitdowntable(table_data, rid, request, seat, roledata)
 
	responsemsg.seat_index = seat.index

	return responsemsg
end

--[Comment]
-- 准备
-- rid  玩家id
-- roledata 玩家信息 {info,money}
-- request 请求包
-- ret 
--
function CMD.gameready(rid, roledata, request)
	local responsemsg = {
	}

    local playermoney = roledata.money or { }
    local table_data = service.table_data
    local seat = tablelogic.get_seat_by_rid(table_data, rid)

    --检查携带量
    local curmoney = tablelogic.get_curmoney({playerinfo = playermoney})
    if tablelogic.is_diamondtable() or tablelogic.is_cointable() then
        local min_carry = table_data.conf.min_carry_amount or 0
        local max_carry = table_data.conf.max_carry_amount or 0
        local cur_carry = curmoney
        if cur_carry < min_carry or cur_carry > max_carry then
            response.retcode = EErrCode.ERR_INVALID_PARAMS
			response.retstr = "携带量不满足入场要求！"
			return	response
        end
	end

	if seat == nil then
		responsemsg.retcode = EErrCode.ERR_HAD_STANDUP
		responsemsg.retstr = "玩家不在座位上！"
		return responsemsg
	end

	if seat.state ~= ECQSSCSeatState.SEAT_STATE_WAIT_READY then
		responsemsg.retcode = EErrCode.ERR_HAD_STANDUP
		responsemsg.retstr = "座位状态不是等待准备状态！"
		return responsemsg
	end

    seat.had_ready = true          --已准备
    seat.ready_timeout_time = 0
	seat.state = ECQSSCSeatState.SEAT_STATE_WAIT_START

    ---取消准备倒计时
	if seat.ready_timer_id > 0  then 
		timer.cleartimer(seat.ready_timer_id)
		seat.ready_timer_id = -1
	end
	tablelogic.gameready(table_data, request, seat, roledata)
    responsemsg.rid = rid
    responsemsg.seat_index = seat.index
    responsemsg.is_ready = true

	return responsemsg
end

--[Comment]
-- 执行玩家操作
-- rid  玩家id
-- roledata 玩家信息 {info,money}
-- request 请求包
-- ret 
--
function CMD.doaction(rid, roledata, request)
	local responsemsg = {}
	local tableobj = service.table_data
	local seatlogic = service:get_logicbyname("seatlogic")
	local seat = tablelogic.get_seat_by_rid(tableobj, rid)
	if seat == nil then
		responsemsg.retcode = EErrCode.ERR_HAD_STANDUP
		responsemsg.retstr = "玩家不在座位上！"
		return responsemsg
	end
	return tablelogic.doaction(tableobj, rid, request, seat)
end

--[Comment]
-- 主动离桌
-- rid  玩家id
-- roledata 玩家信息 {info,money}
-- request 请求包
-- ret 
--
function CMD.leavetable(rid, roledata, request)
	local responsemsg = {}
	local table_data = service.table_data

	local seat = tablelogic.get_seat_by_rid(table_data, rid)
	if seat == nil then --在旁观列表，直接离开
		local curmoney = tablelogic.get_curmoney(table_data.waits[rid])
		tablelogic.leavetable(table_data, request, rid, curmoney)	
		return responsemsg
	end

	----如果在游戏中,且玩家已下注，不能让他退出房间
	-- if not tablelogic.is_onegameend(table_data) and (seat.cur_total_bet > 0 or seat.is_banker) then
	-- 	responsemsg.retcode = EErrCode.ERR_PLAYER_IN_GAME
	-- 	responsemsg.retstr = "游戏中,不能退出！"
	-- 	return responsemsg
	-- end

    --先站起，再离开
    local curmoney = tablelogic.get_curmoney(seat)
	tablelogic.standuptable(table_data, request, seat)
	tablelogic.leavetable(table_data, request, rid, curmoney)	

    responsemsg.rid = rid
	responsemsg.table_index = table_data.index

	return responsemsg
end

--
--断线重连
--
-- 获得桌子状态，获得操作状态
-- 将桌子状态、操作状态、桌子信息、座位信息、玩家信息发给客户端
--
function CMD.reentertable(rid, roledata, request)
	local responsemsg = {}

    ---filelog.print("-------------reenter table--------",rid)
    local seatlogic = service:get_logicbyname("seatlogic")
	local tableobj = service.table_data
	local playerinfo = roledata.info or {}
    local playermoney = roledata.money or {}
    local table_state = tableobj.state

     --桌子索引错误
    if request and request.table_index and request.table_index ~= tableobj.index then
        --从当前桌子离开
        local curmoney = tablelogic.get_curmoney({playerinfo = playermoney})
        skynet.send(".router","lua","leave_table",nil,rid,tableobj.index,curmoney)
        return {retcode = EErrCode.ERR_INVALID_REQUEST,retstr = "错误的桌子索引号！"}
    end

	local seat = tablelogic.get_seat_by_rid(tableobj, rid)
	if seat ~= nil then
		seat.playerinfo.rolename = playerinfo.rolename
		seat.playerinfo.logo = playerinfo.logo
		seat.playerinfo.sex = playerinfo.sex

        --初始化seat数据
	    seat.playerinfo.ip_addr = roledata.ip_addr or playerinfo.ip_addr
        seat.playerinfo.gps_addr = roledata.gps_addr or playerinfo.gps_addr
        seat.playerinfo.intro = playerinfo.intro or ""
	    seat.playerinfo.coin = playermoney.coin or 0
        seat.playerinfo.lock_coin = playermoney.lock_coin or 0
        seat.playerinfo.diamond = playermoney.diamond or 0
        seat.playerinfo.lock_diamond = playermoney.lock_diamond or 0
	end

	if seat == nil then
		local ret = CMD.entertable(rid,roledata)
        if ret and ret.retcode ~= nil then
             skynet.send(".router","lua","leave_table",nil,rid,tableobj.index,playermoney.coin)
        end
        return ret
	end

    --返回游戏信息大集合
	responsemsg.table_gameinfo = tablelogic.copy_table_gameinfo(seat.index)

    --延迟一段时间
    local timerid = timer.settimer(3,"reenter_table",{seat_index = seat.index })

    --更改断线状态
    if seat.is_disconnected then
	    seat.is_disconnected = false
    end

    --清除断线计时器
    if seat.disconnect_timer_id > 0 then
        timer.cleartimer(seat.disconnect_timer_id)
        seat.disconnect_timer_id = -1
    end

	return responsemsg
end

--
--玩家断开连接
--
function CMD.disconnect(rid, roledata,request)
	filelog.print("----tablerequest.disconnect----", rid)
	local tableobj = service.table_data
    local seat = tablelogic.get_seat_by_rid(tableobj,rid)
    if seat then
        --tablelogic.disconnect(tableobj,request,seat)
        ---先站起，再离开
        local curmoney = tablelogic.get_curmoney(seat)
        tablelogic.standuptable(tableobj, request, seat)
        tablelogic.leavetable(tableobj, request, rid, curmoney)   
    end

    return true
end

--
--站起
--
function CMD.standuptable(rid, roledata,request)
    local responsemsg = { }
    local tableobj = service.table_data
    local seat = tablelogic.get_seat_by_rid(tableobj,rid)

    if seat == nil then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不在座位上!"
        return responsemsg
    end

    --如果玩家在游戏中,不能让他退出房间
	if not tablelogic.is_onegameend(tableobj) and (seat.cur_total_bet > 0 or seat.is_banker) then
		responsemsg.retcode = EErrCode.ERR_PLAYER_IN_GAME
		responsemsg.retstr = "游戏中,不能退出！"
		return responsemsg
	end
    tablelogic.standuptable(tableobj, request, seat)

    return responsemsg
end

function CMD.getbetrecord(rid, roledata, request)
    local responsemsg = {}
    local tableobj = service.table_data
    local seat = tablelogic.get_seat_by_rid(tableobj, rid) 
    if seat == nil then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不在座位上"
        return responsemsg
    end
    responsemsg.recorditems = tablelogic.getbetrecord(rid)
    return responsemsg
end

--
--获取玩家列表
--
function CMD.getplayerlist(rid, roledata, request)
    local responsemsg = { }
    local tableobj = service.table_data
    local seat = tablelogic.get_seat_by_rid(tableobj,rid)

    if seat == nil then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不在座位上!"
        return responsemsg
    end

    return tablelogic.getplayerlist(tableobj, request, seat)
end

--
--获取上庄列表
--
function CMD.getupbankerlist(rid, roledata, request)
    local responsemsg = { }
    local tableobj = service.table_data
    local seat = tablelogic.get_seat_by_rid(tableobj,rid)

    if seat == nil then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不在座位上!"
        return responsemsg
    end

    return tablelogic.getupbankerlist(tableobj, request, seat)
end

--
--清除玩家状态
--
function CMD.clear_player_state(rid, roledata, request)
    if not rid or rid <= 0 then
        return
    end

    local tableobj = service.table_data
    if tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_ALL_READY
    or tableobj.state == ECQSSCTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN then
        CMD.leavetable(rid, roledata, request)
    end
end

-----------------

--
-- 玩家钻石改变时的通知，来自gate
--
function CMD.rid_change_diamond(rid, begindiamond, value, enddiamond)
	print(filename .. "line98", rid, begindiamond, value, enddiamond)

    if enddiamond ~= begindiamond + value then
        return false
    end

    local tableobj = service.table_data
    for _,seat in pairs(tableobj.seats) do
        if seat.rid == rid then
            if seat.playerinfo.diamond ~= begindiamond then
                return false
            end
            seat.playerinfo.diamond = enddiamond
           
            --通知客户端
            local noticemsg = {
                money_change_list = { },
            }
            table.insert(noticemsg.money_change_list,{rid = rid,money_type = EMoneyType.DIAMOND,change_value = value,final_value = enddiamond})
            tablelogic.sendmsg_to_alltableplayer(tableobj,"moneychangeN",noticemsg)
            break
        end
    end
   
   return true 
end

--
-- 玩家金币改变时的通知，来自gate
--
function CMD.rid_change_coin(rid, begincoin, value, endcoin)
	print(filename .. "line98", rid, begincoin, value, endcoin)

    if endcoin ~= begincoin + value then
        return false
    end

    local tableobj = service.table_data
    for _,seat in pairs(tableobj.seats) do
        if seat.rid == rid then
            if seat.playerinfo.coin ~= begincoin then
                return false
            end
            seat.playerinfo.coin = endcoin
           
            --通知客户端
            local noticemsg = {
                money_change_list = { },
            }
            table.insert(noticemsg.money_change_list,{rid = rid,money_type = EMoneyType.COIN,change_value = value,final_value = endcoin})
            tablelogic.sendmsg_to_alltableplayer(tableobj,"moneychangeN",noticemsg)
            break
        end
    end
   
   return true 
end
------------------------------------------------------------------

return CMD